﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using StructureMap;
using StructureMap.Configuration.DSL;

using ProjectBase.Core;
using ProjectBase.Core.Web;
using ProjectBase.Core.Service;

namespace Survey.Tools.IoC
{
    [CLSCompliant(false)]
    public partial class StructureMapFactoryProvider : IFactoryProvider
    {
        #region static FactoryProvider Init
        static StructureMapFactoryProvider()
        {
            ObjectFactory.Initialize(x =>
            {
                x.UseDefaultStructureMapConfigFile = false;

                // defaults
                SetScans(x);

                // setter injection with proxy 'promises'
                SetSetterInjection(x);

                // Defaults
                x.IncludeRegistry<DefaultProfileRegistry>();
            });

            ObjectFactory.Container.SetDefaultsToProfile("DefaultProfile");
        }

        static void SetScans(IRegistry x)
        {
            // wrapped with proxy
            x.Scan(s =>
            {
                s.AssembliesFromApplicationBaseDirectory(
                    af => af.FullName.StartsWith("ProjectBase")
                       || af.FullName.StartsWith("Survey"));

                s.Exclude(type => !type.IsClass);
                s.Exclude(type => type.IsAbstract);

                s.Include(type => type.GetInterfaces().Any(t => t.IsEquivalentTo(typeof(IService))));

                s.Convention<ProxyConvention>();

                s.WithDefaultConventions();
            });
        }

        static void SetSetterInjection(IRegistry x)
        {
            x.SetAllProperties
            (
                set => set.TypeMatches
                (
                    type => type != typeof(IEntityModel<,>) // not intended for IoC
                         && type != typeof(IViewModel)       // not intended for IoC
                         && type.GetInterfaces().Any(i => i.IsEquivalentTo(typeof(IService)))
                )
            );

            // Messages act as only ONE instance for any IMessageHolder in the scope of a single Request
            x.SetAllProperties(set => set.OfType<Messages>());
            x.For<Messages>()
                .HybridHttpOrThreadLocalScoped()
                .Use<Messages>();
        }
        public static void ResetDefaults()
        {
            ObjectFactory.ResetDefaults();
            ObjectFactory.Container.SetDefaultsToProfile("DefaultProfile");
        }
        #endregion static FactoryProvider Init

        #region IFactoryProvider Members

        public virtual object GetService(Type serviceType)
        {
            return CreateInstance(serviceType);
        }

        public virtual T CreateInstance<T>(string name = null, Type implementor = null)
            where T : class, IService
        {
            return CreateInstance(typeof(T), name, implementor) as T;
        }

        public virtual object CreateInstance(Type type, string name = null, Type implementor = null)
        {
            var instance = name.IsNotEmpty()
                ? ObjectFactory.GetNamedInstance(type, name)
                : ObjectFactory.GetInstance(implementor ?? type);

            return instance;
        }

        public virtual IEnumerable<T> CreateInstances<T>()
            where T : class, IService
        {
            return ObjectFactory.GetAllInstances<T>();
        }

        /// <summary>
        ///     Injects dependencies via setters. Intended for 'external framework' created instances, e.g. aspx Page
        /// </summary>
        public virtual void Enrich<T>(T instance)
        {
            ObjectFactory.BuildUp(instance);
        }
        #endregion
    }
}
